#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @FileName  :functions.py
# @Time      :2024/10/17 18:24
# @Author    :zhou_yi

"""
功能软件

"""
import random
import csv
import time
from pathlib import Path
from datetime import datetime, date, timedelta
import random as rd
from dateutil.relativedelta import relativedelta
import re
import uuid
import pandas as pd
from docxtpl import DocxTemplate


# 人民币金额转大写
def rmb_upper(value: int | float) -> str:
    """
        人民币大写
    :param value: 传入浮点类型的值返回 unicode 字符串
    :return:
    """
    map_ = [u"零", u"壹", u"贰", u"叁", u"肆", u"伍", u"陆", u"柒", u"捌", u"玖"]
    unit = [u"分", u"角", u"元", u"拾", u"百", u"千", u"万", u"拾", u"百", u"千", u"亿",
            u"拾", u"百", u"千", u"万", u"拾", u"百", u"千", u"兆"]

    nums = []  # 取出每一位数字，整数用字符方式转换避大数出现误差
    for i in range(len(unit) - 3, -3, -1):
        if value >= 10 ** i or i < 1:
            nums.append(int(round(value / (10 ** i), 2)) % 10)

    words = []
    flag = 0  # 标记连续0次数，以删除万字，或适时插入零字
    start = len(nums) - 3
    for i in range(start, -3, -1):  # 使i对应实际位数，负数为角分
        if 0 != nums[start - i] or len(words) == 0:
            if flag:
                words.append(map_[0])
                flag = 0
            words.append(map_[nums[start - i]])
            words.append(unit[i + 2])
        elif 0 == i or (0 == i % 4 and flag < 3):  # 控制‘万/元’
            words.append(unit[i + 2])
            flag = 0
        else:
            flag += 1

    if words[-1] != unit[0]:  # 结尾非‘分’ 补 '整'字
        words.append(u"整")
    return ''.join(words)


# 格式化文件对象
def date_format_str(dt: datetime, fmt="%Y年%m月%d日") -> str:
    date_str = datetime.strftime(dt, fmt)
    return date_str


# 日期随机格式化
def random_date_format(dt: datetime | date, fmt_lst: list | tuple = None) -> str:
    """
        日期对象随机格式化成字符串
    :param dt:
    :param fmt_lst:
    :return:
    """
    if fmt_lst is None:
        fmt_lst = ["%Y-%m-%d", "%Y年%m月%d日", "%Y/%m/%d", "%Y.%m.%d"]

    fmt = rd.choice(fmt_lst)
    date_str = datetime.strftime(dt, fmt)
    return date_str


# 时间节点前多少天的随机日期
def random_date_front(dt: datetime | date, days: int = 10) -> date | datetime:
    """
        时间节点前日期
    :param dt:
    :param days:
    :return:
    """
    _day = rd.randint(2, days)  # dt,日期前day天
    _date = dt - timedelta(_day)  # dt 日期向前day天
    return _date


# 时间+月返回新的时间对象
def date_add_months(dt: datetime | date, months: int = 1) -> datetime | date:
    """
        用于合同服务期的计算 当前日期对象增加1个月，时间相对应
        pip install python-dateutil
        from dateutil.relativedelta import relativedelta

    :param dt:
    :param months:
    :return:
    """
    end = dt + relativedelta(months=months)
    end = end - timedelta(days=1)
    return end


# 两个时间对象之间的差月数
def months_of_date(dt1: datetime | date, dt2: datetime | date) -> int:
    """
    合同签订日期：2024年7月1日~2025年6月30日 闭合区间
    :param dt1: 起始时间
    :param dt2: 结束时间
    :return: 两个日期之间的月数
    """

    _years = relativedelta(dt2, dt1).years
    _months = relativedelta(dt2, dt1).months
    _days = relativedelta(dt2, dt1).days

    # 大于15天进位1个月
    res = _years * 12 + _months if _days < 15 else _years * 12 + _months + 1

    return res


# 正则匹配，文件夹下的文件名含有2个关键字符
def re_get_files(path: str | Path, key: str, filemode='*') -> dict:
    """
        选出文件夹里文件名含有2个关键字符的 文件字典
        在模版目录下有选择的输出相对应的模版文件
    :param path: 目录
    :param key: 关键字
    :param filemode:文件类型
    :return: {文件名：全名} 没有匹配上就输出{}
    """
    # 获取文件夹下文件列表输出以文件名为key的字典，字典的值为文件全名
    path = Path(path)
    if not path.is_dir():
        raise "参数错误,不是目录名"
    _filename_dic = {name.stem: name for name in path.glob(pattern=filemode)}  # 获取{文件名：全名}

    # 正则匹配 字符串包含特殊关键字符

    k1, k2 = key.split('_')  # '三方比价_有害垃圾'=>['三方比价','有害垃圾']

    pattern = f"{k1}.*{k2}|{k2}.*{k1}"  # 定义正则(文件中包含这两个关键值)

    _res = {}
    for name in _filename_dic.keys():
        match = re.search(pattern=pattern, string=name)
        if match:
            _res[name] = _filename_dic[name]

    return _res


# 转换文件字符编吗
def gbk_to_utf8(filename, utf8filename):
    # 读取GBK编码的文件
    with open(filename, 'r', encoding='gbk') as f:
        content = f.read()

    # 写入UTF-8编码的文件
    with open(utf8filename, 'w', encoding='utf-8') as f:
        f.write(content)

    print('ok')


# 数字检查
def digital_inspection(d) -> float:
    try:
        _res = float(d)
    except:
        _res = float(0)

    return _res


# 生成唯一字符串
def uid_key() -> str:
    _uid = uuid.uuid4()
    return _uid.__str__()


# 从字典列表里求 已知key值 对应的字典
def find_dic_from_lst(find_key: str, value, lst_dic: list[dict]) -> list:
    """

    :param find_key: 字典的 key
    :param value: 匹配的值
    :param lst_dic: 待查找的目标
    :return: 匹配的字典列表
    """

    return [dic for dic in lst_dic if dic[find_key] == value]


# 列表字典转df 并更换表头
def df_show(lst: list[dict], cols_map: dict = None) -> pd.DataFrame:
    if cols_map:
        _df = pd.DataFrame(lst)
        _df = _df[list(cols_map.keys())]  # 按照映射字典的key排列表头
        _df = _df.rename(columns=cols_map)
        return _df
    else:
        return pd.DataFrame(lst)


# 模板生成word文件
def word_by_tpl(tpl: str, context: dict, filename: str):
    try:
        _docx = DocxTemplate(template_file=tpl)
        _docx.render(context=context)
        _docx.save(filename)

        return filename

    except:
        return False


# 输入一个整数 分成8个随机数
def rtn_random_8(d: int):
    sp: int = d // 8
    num7 = [random.randint(0, sp) for i in range(7)]
    num_8 = d - sum(num7)
    num7.append(num_8)
    random.shuffle(num7)  # 列表顺序随机
    return num7


# 字典追加进csv 文件
def dict_to_csv(filename: str, data: list[dict]):
    path = Path(filename)
    if path.exists():
        with open(path, mode='a', newline='', encoding='utf-8') as file:
            # 创建一个csv.DictWriter对象，指定字段名
            writer = csv.DictWriter(file, fieldnames=data[0].keys())

            # 写入数据行
            for row in data:
                writer.writerow(row)
    else:
        with open(path, mode='a', newline='', encoding='utf-8') as file:
            # 创建一个csv.DictWriter对象，指定字段名
            writer = csv.DictWriter(file, fieldnames=data[0].keys())

            # 写入标题行
            writer.writeheader()

            # 写入数据行
            for row in data:
                writer.writerow(row)


# 日期对象转为日期时间对象
def date_to_datetime(dt):
    return datetime.combine(dt, datetime.min.time())


if __name__ == '__main__':
    # print(rtn_random_8(0))
    # for i in range(10):
    #     print(uid_key())
    # gbk = r"E:\py_code\prj_5\database\address.csv"
    # utf8 = r"E:\py_code\prj_5\database\address_utf8.csv"
    # print(digital_inspection(5))
    # gbk_to_utf8(gbk, utf8)

    # _list = ['三方比价_有害垃圾', '清运合同_有害垃圾', '清运记录_有害垃圾']
    #
    # print(re_get_files("../tpl", '三方比价_有害垃圾', filemode='*.docx'))

    # d1 = date(2024, 7, 1)
    # d2 = datetime(2026, 6, 30)

    # print(months_of_date(d1, d2))
    # print(date_add_months(d1))
    # print((d1 - d1).days)
    # print(random_format_date(d))
    # print(random_date_front(d, 10))

    ...
